﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved All Rights Reserved All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Data;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using System.ComponentModel;
using System.Xaml;
using System.Dynamic;
using System.Reflection;
using System.Threading;
using System.Collections.Specialized;
using FinPlusCommon;
using u = FinPlusUtility.Utility;
using log = Logger.Logger;

namespace FinPlusWCFConnData
{
    public class FinPlusServiceConn 
    {
        private static ConcurrentDictionary<string, ServiceConn> _serviceConns = new ConcurrentDictionary<string, ServiceConn>();

        //public
        public void Connect(u.Env env, string config, string user, string serviceKey, string serviceType, string parms, bool isTransposed = true, bool isAsync = false)
        {
            try
            {
                ServiceConn serviceConn;
                lock (_serviceConns)
                {
                    if (_serviceConns.ContainsKey(serviceKey)) return;
                        _serviceConns.TryAdd(serviceKey,  serviceConn = new ServiceConn(env, config, user, serviceKey, serviceType, parms, isTransposed, isAsync));
                }
                serviceConn.GetFunctions();
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to connect serviceType={0}, serviceKey={1}, params={2}", serviceType, serviceKey, parms), e);
                throw e;
            }
        }

        public void Connect(u.Env env, string config, string user, string serviceKey, string serviceType, string xmlPath, string node, bool isTransposed = true)
        {
            try
            {
                lock (_serviceConns)
                {
                    _serviceConns.TryAdd(serviceKey, new ServiceConn(xmlPath, node, isTransposed));
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to connect: serviceType={0}, serviceKey={1}, xmlPath={2}, node={3}", serviceType, serviceKey, xmlPath, node), e);
                throw e;
            }
        }

        public void Save(string serviceKey, IFinPlusFunction func)
        {
            try
            {
                lock (_serviceConns)
                {
                    ServiceConn serviceConn;
                    if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                        serviceConn.SaveFunction(func, ChangeType.New);
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to save: serviceKey={0} function {1}", serviceKey, func.ToString()), e);
            }
        }

        public void Dispose(string serviceKey)
        {
            lock (_serviceConns)
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryRemove(serviceKey, out serviceConn))
                    serviceConn.Dispose();
            }
        }

        public static string GetServiceKey(string serviceName, string parms, string KeyFormat)
        {
            if(KeyFormat == string.Empty) return serviceName;

            var key =  new StringBuilder();

            var p = u.ToDictionary(parms, true, ';', ',');
          
            foreach (var KeyItem in u.StringToArray1d(KeyFormat, ','))
                if (p.ContainsKey(KeyItem.ToString()))
                    key.Append("|" + p[KeyItem.ToString()]);

            return string.Format("{0} {1}", serviceName, string.IsNullOrEmpty(key.ToString()) ? KeyFormat : key.ToString());
        }

        public FuncDynamics GetFuncDynamics(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return serviceConn.DynFuncs;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return null;
        }

        public IFinPlusFunctions GetFunctions(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return serviceConn.RegFuncs;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return null;
        }

        public bool HasCompleted(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return _serviceConns[serviceKey].HasCompleted;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return true;
        }
    }
}

